#
# Copyright 2018 Quantopian, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from datetime import time

import pandas as pd
from pytz import timezone

from .precomputed_trading_calendar import PrecomputedTradingCalendar

precomputed_krx_holidays = pd.to_datetime([
    "1986-01-01",
    "1986-01-02",
    "1986-01-03",
    "1986-03-10",
    "1986-05-05",
    "1986-05-16",
    "1986-06-06",
    "1986-07-17",
    "1986-08-15",
    "1986-09-18",
    "1986-10-01",
    "1986-10-03",
    "1986-10-09",
    "1986-12-25",
    "1986-12-29",
    "1986-12-30",
    "1986-12-31",
    "1987-01-01",
    "1987-01-02",
    "1987-01-29",
    "1987-03-10",
    "1987-05-05",
    "1987-07-17",
    "1987-10-01",
    "1987-10-07",
    "1987-10-08",
    "1987-10-09",
    "1987-12-25",
    "1987-12-28",
    "1987-12-29",
    "1987-12-30",
    "1987-12-31",
    "1988-01-01",
    "1988-02-18",
    "1988-03-01",
    "1988-03-10",
    "1988-04-05",
    "1988-05-05",
    "1988-05-23",
    "1988-06-06",
    "1988-08-15",
    "1988-09-26",
    "1988-10-03",
    "1988-12-27",
    "1988-12-28",
    "1988-12-29",
    "1988-12-30",
    "1989-01-02",
    "1989-01-03",
    "1989-02-06",
    "1989-03-01",
    "1989-03-10",
    "1989-04-05",
    "1989-05-05",
    "1989-05-12",
    "1989-06-06",
    "1989-07-17",
    "1989-08-15",
    "1989-09-14",
    "1989-09-15",
    "1989-10-12",
    "1989-12-25",
    "1990-01-01",
    "1990-01-02",
    "1990-01-26",
    "1990-03-01",
    "1990-04-05",
    "1990-05-02",
    "1990-06-06",
    "1990-07-17",
    "1990-08-15",
    "1990-10-01",
    "1990-10-02",
    "1990-10-03",
    "1990-10-04",
    "1990-10-09",
    "1990-12-25",
    "1990-12-27",
    "1990-12-28",
    "1990-12-31",
    "1991-01-02",
    "1991-02-14",
    "1991-02-15",
    "1991-03-01",
    "1991-04-05",
    "1991-05-21",
    "1991-06-06",
    "1991-07-17",
    "1991-08-15",
    "1991-09-23",
    "1991-10-03",
    "1991-12-25",
    "1991-12-27",
    "1991-12-30",
    "1991-12-31",
    "1992-01-01",
    "1992-01-02",
    "1992-02-03",
    "1992-02-04",
    "1992-02-05",
    "1992-03-10",
    "1992-05-05",
    "1992-07-17",
    "1992-09-10",
    "1992-09-11",
    "1992-12-25",
    "1992-12-28",
    "1992-12-29",
    "1992-12-30",
    "1992-12-31",
    "1993-01-01",
    "1993-01-22",
    "1993-03-01",
    "1993-03-10",
    "1993-04-05",
    "1993-05-05",
    "1993-05-28",
    "1993-07-07",
    "1993-09-29",
    "1993-09-30",
    "1993-10-01",
    "1994-01-03",
    "1994-02-09",
    "1994-02-10",
    "1994-02-11",
    "1994-02-14",
    "1994-03-01",
    "1994-04-05",
    "1994-05-05",
    "1994-05-18",
    "1994-05-20",
    "1994-06-06",
    "1994-08-15",
    "1994-09-19",
    "1994-09-20",
    "1994-09-21",
    "1994-10-03",
    "1994-12-29",
    "1994-12-30",
    "1995-01-02",
    "1995-01-30",
    "1995-01-31",
    "1995-02-01",
    "1995-03-01",
    "1995-04-05",
    "1995-05-01",
    "1995-05-05",
    "1995-06-06",
    "1995-07-17",
    "1995-08-15",
    "1995-09-08",
    "1995-10-03",
    "1995-12-25",
    "1995-12-29",
    "1996-01-01",
    "1996-01-02",
    "1996-03-01",
    "1996-04-05",
    "1996-05-01",
    "1996-05-24",
    "1996-06-06",
    "1996-07-17",
    "1996-08-15",
    "1996-09-26",
    "1996-09-27",
    "1996-10-03",
    "1996-12-25",
    "1996-12-30",
    "1996-12-31",
    "1997-01-01",
    "1997-02-07",
    "1997-05-05",
    "1997-06-06",
    "1997-07-17",
    "1997-08-15",
    "1997-09-15",
    "1997-09-16",
    "1997-09-17",
    "1997-10-03",
    "1997-12-25",
    "1997-12-30",
    "1997-12-31",
    "1998-01-01",
    "1998-01-02",
    "1998-01-27",
    "1998-01-28",
    "1998-01-29",
    "1998-05-01",
    "1998-05-05",
    "1998-07-17",
    "1998-10-05",
    "1998-10-06",
    "1998-12-25",
    "1998-12-29",
    "1998-12-30",
    "1998-12-31",
    "1999-01-01",
    "1999-02-15",
    "1999-02-16",
    "1999-02-17",
    "1999-03-01",
    "1999-04-05",
    "1999-05-05",
    "1999-09-23",
    "1999-09-24",
    "1999-12-29",
    "1999-12-30",
    "1999-12-31",
    "2000-01-03",
    "2000-02-04",
    "2000-03-01",
    "2000-04-05",
    "2000-04-13",
    "2000-05-01",
    "2000-05-05",
    "2000-05-11",
    "2000-06-06",
    "2000-07-17",
    "2000-08-15",
    "2000-09-11",
    "2000-09-12",
    "2000-09-13",
    "2000-10-03",
    "2000-12-25",
    "2000-12-27",
    "2000-12-28",
    "2000-12-29",
    "2001-01-01",
    "2001-01-23",
    "2001-01-24",
    "2001-01-25",
    "2001-03-01",
    "2001-04-05",
    "2001-05-01",
    "2001-06-06",
    "2001-07-17",
    "2001-08-15",
    "2001-10-01",
    "2001-10-02",
    "2001-10-03",
    "2001-12-25",
    "2001-12-31",
    "2002-01-01",
    "2002-02-11",
    "2002-02-12",
    "2002-02-13",
    "2002-03-01",
    "2002-04-05",
    "2002-05-01",
    "2002-06-06",
    "2002-06-13",
    "2002-07-01",
    "2002-07-17",
    "2002-08-15",
    "2002-09-20",
    "2002-10-03",
    "2002-12-19",
    "2002-12-25",
    "2002-12-31",
    "2003-01-01",
    "2003-01-31",
    "2003-05-01",
    "2003-05-05",
    "2003-05-08",
    "2003-06-06",
    "2003-07-17",
    "2003-08-15",
    "2003-09-10",
    "2003-09-11",
    "2003-09-12",
    "2003-10-03",
    "2003-12-25",
    "2003-12-31",
    "2004-01-01",
    "2004-01-21",
    "2004-01-22",
    "2004-01-23",
    "2004-03-01",
    "2004-04-05",
    "2004-04-15",
    "2004-05-05",
    "2004-05-26",
    "2004-09-27",
    "2004-09-28",
    "2004-09-29",
    "2004-12-31",
    "2005-02-08",
    "2005-02-09",
    "2005-02-10",
    "2005-03-01",
    "2005-04-05",
    "2005-05-05",
    "2005-06-06",
    "2005-08-15",
    "2005-09-19",
    "2005-10-03",
    "2005-12-30",
    "2006-01-30",
    "2006-03-01",
    "2006-05-01",
    "2006-05-05",
    "2006-05-31",
    "2006-06-06",
    "2006-07-17",
    "2006-08-15",
    "2006-10-03",
    "2006-10-05",
    "2006-10-06",
    "2006-12-25",
    "2006-12-29",
    "2007-01-01",
    "2007-02-19",
    "2007-03-01",
    "2007-05-01",
    "2007-05-24",
    "2007-06-06",
    "2007-07-17",
    "2007-08-15",
    "2007-09-24",
    "2007-09-25",
    "2007-09-26",
    "2007-10-03",
    "2007-12-19",
    "2007-12-25",
    "2007-12-31",
    "2008-01-01",
    "2008-02-06",
    "2008-02-07",
    "2008-02-08",
    "2008-04-09",
    "2008-05-01",
    "2008-05-05",
    "2008-05-12",
    "2008-06-06",
    "2008-08-15",
    "2008-09-15",
    "2008-10-03",
    "2008-12-25",
    "2008-12-31",
    "2009-01-01",
    "2009-01-26",
    "2009-01-27",
    "2009-05-01",
    "2009-05-05",
    "2009-10-02",
    "2009-12-25",
    "2009-12-31",
    "2010-01-01",
    "2010-02-15",
    "2010-03-01",
    "2010-05-05",
    "2010-05-21",
    "2010-06-02",
    "2010-09-21",
    "2010-09-22",
    "2010-09-23",
    "2010-12-31",
    "2011-02-02",
    "2011-02-03",
    "2011-02-04",
    "2011-03-01",
    "2011-05-05",
    "2011-05-10",
    "2011-06-06",
    "2011-08-15",
    "2011-09-12",
    "2011-09-13",
    "2011-10-03",
    "2011-12-30",
    "2012-01-23",
    "2012-01-24",
    "2012-03-01",
    "2012-04-11",
    "2012-05-01",
    "2012-05-28",
    "2012-06-06",
    "2012-08-15",
    "2012-10-01",
    "2012-10-03",
    "2012-12-19",
    "2012-12-25",
    "2012-12-31",
    "2013-01-01",
    "2013-02-11",
    "2013-03-01",
    "2013-05-01",
    "2013-05-17",
    "2013-06-06",
    "2013-08-15",
    "2013-09-18",
    "2013-09-19",
    "2013-09-20",
    "2013-10-03",
    "2013-10-09",
    "2013-12-25",
    "2013-12-31",
    "2014-01-01",
    "2014-01-30",
    "2014-01-31",
    "2014-05-01",
    "2014-05-05",
    "2014-05-06",
    "2014-06-04",
    "2014-06-06",
    "2014-08-15",
    "2014-09-08",
    "2014-09-09",
    "2014-09-10",
    "2014-10-03",
    "2014-10-09",
    "2014-12-25",
    "2014-12-31",
    "2015-01-01",
    "2015-02-18",
    "2015-02-19",
    "2015-02-20",
    "2015-05-01",
    "2015-05-05",
    "2015-05-25",
    "2015-08-14",
    "2015-09-28",
    "2015-09-29",
    "2015-10-09",
    "2015-12-25",
    "2015-12-31",
    "2016-01-01",
    "2016-02-08",
    "2016-02-09",
    "2016-02-10",
    "2016-03-01",
    "2016-04-13",
    "2016-05-05",
    "2016-05-06",
    "2016-06-06",
    "2016-08-15",
    "2016-09-14",
    "2016-09-15",
    "2016-09-16",
    "2016-10-03",
    "2016-12-30",
    "2017-01-27",
    "2017-01-30",
    "2017-03-01",
    "2017-05-01",
    "2017-05-03",
    "2017-05-05",
    "2017-05-09",
    "2017-06-06",
    "2017-08-15",
    "2017-10-02",
    "2017-10-03",
    "2017-10-04",
    "2017-10-05",
    "2017-10-06",
    "2017-10-09",
    "2017-12-25",
    "2017-12-29",
    "2018-01-01",
    "2018-02-15",
    "2018-02-16",
    "2018-03-01",
    "2018-05-01",
    "2018-05-07",
    "2018-05-22",
    "2018-06-06",
    "2018-06-13",
    "2018-08-15",
    "2018-09-24",
    "2018-09-25",
    "2018-09-26",
    "2018-10-03",
    "2018-10-09",
    "2018-12-25",
    "2018-12-31",
    "2019-01-01",
    "2019-02-04",
    "2019-02-05",
    "2019-02-06",
    "2019-03-01",
    "2019-05-01",
    "2019-05-06",
    "2019-06-06",
    "2019-08-15",
    "2019-09-12",
    "2019-09-13",
    "2019-10-03",
    "2019-10-09",
    "2019-12-25",
    "2019-12-31",
    "2020-01-01",
    "2020-01-24",
    "2020-01-27",
    "2020-04-15",
    "2020-04-30",
    "2020-05-01",
    "2020-05-05",
    "2020-08-17",
    "2020-09-30",
    "2020-10-01",
    "2020-10-02",
    "2020-10-09",
    "2020-12-25",
    "2020-12-31",
    "2021-01-01",
    "2021-02-11",
    "2021-02-12",
    "2021-03-01",
    "2021-05-05",
    "2021-05-19",
    "2021-09-20",
    "2021-09-21",
    "2021-09-22",
    "2021-12-31",
])


class XKRXExchangeCalendar(PrecomputedTradingCalendar):
    """
    Calendar for the Korea exchange, and the primary calendar for
    the country of South Korea.

    Open Time: 9:00 AM, KST (Korean Standard Time)
    Close Time: 3:30 PM, KST (Korean Standard Time)

    NOTE: Korea observes Standard Time year-round.

    Due to the complexity around the Korean holidays, we are hardcoding
    a list of holidays covering 1986-2019, inclusive.

    Regularly-Observed Holidays:
    - Seollal (New Year's Day)
    - Independence Movement Day
    - Labor Day
    - Buddha's Birthday
    - Memorial Day
    - Provincial Election Day
    - Liberation Day
    - Chuseok (Korean Thanksgiving)
    - National Foundation Day
    - Christmas Day
    - End of Year Holiday

    NOTE: Hangeul Day became a national holiday in 2013
    - Hangeul Proclamation Day
    """
    tz = timezone('Asia/Seoul')

    open_times = (
        (None, time(9, 1)),
    )
    close_times = (
        (None, time(15, 30)),
    )

    def __init__(self, *args, **kwargs):
        super(XKRXExchangeCalendar, self).__init__(*args, **kwargs)

    @property
    def name(self):
        # Korea Exchange
        return 'XKRX'

    @property
    def precomputed_holidays(self):
        return precomputed_krx_holidays
